﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using MessageBox = System.Windows.MessageBox;
using Size = System.Windows.Size;

namespace DW.Library
{
    public class DeviceInfo
    {
        public bool IsPrimary { get; set; }
        public string DeviceID { get; set; }

        public string DeviceName { get; set; }
        public Rect ViewportBounds
        {
            get
            {
                Rect rect = new Rect();
                rect.X = dm.dmPosition.x;
                rect.Y = dm.dmPosition.y;
                rect.Width = dm.dmPelsWidth;
                rect.Height = dm.dmPelsHeight;
                return rect;
            }
        }
        public DEVMODE dm { get; set; }
    }
    public enum DEVMODE_SETTINGS
    {
        ENUM_CURRENT_SETTINGS = (-1),
        ENUM_REGISTRY_SETTINGS = (-2)
    }
    public enum CDSMODEL
    {
        CDS_UPDATEREGISTRY = 0x01,
        CDS_NORESET = 0x10000000,
        CDS_TEST = 0x02
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct DEVMODE
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dmDeviceName;

        [MarshalAs(UnmanagedType.U2)]
        public UInt16 dmSpecVersion;

        [MarshalAs(UnmanagedType.U2)]
        public UInt16 dmDriverVersion;

        [MarshalAs(UnmanagedType.U2)]
        public UInt16 dmSize;

        [MarshalAs(UnmanagedType.U2)]
        public UInt16 dmDriverExtra;

        [MarshalAs(UnmanagedType.U4)]
        public DEVMODE_Flags dmFields;

        public POINTL dmPosition;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmDisplayOrientation;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmDisplayFixedOutput;

        [MarshalAs(UnmanagedType.I2)]
        public Int16 dmColor;

        [MarshalAs(UnmanagedType.I2)]
        public Int16 dmDuplex;

        [MarshalAs(UnmanagedType.I2)]
        public Int16 dmYResolution;

        [MarshalAs(UnmanagedType.I2)]
        public Int16 dmTTOption;

        [MarshalAs(UnmanagedType.I2)]
        public Int16 dmCollate;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dmFormName;

        [MarshalAs(UnmanagedType.U2)]
        public UInt16 dmLogPixels;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmBitsPerPel;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmPelsWidth;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmPelsHeight;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmDisplayFlags;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmDisplayFrequency;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmICMMethod;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmICMIntent;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmMediaType;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmDitherType;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmReserved1;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmReserved2;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmPanningWidth;

        [MarshalAs(UnmanagedType.U4)]
        public UInt32 dmPanningHeight;
    }


    public enum DEVMODE_Flags
    {
        DM_BITSPERPEL = 0x40000,
        DM_DISPLAYFLAGS = 0x200000,
        DM_DISPLAYFREQUENCY = 0x400000,
        DM_PELSHEIGHT = 0x100000,
        DM_PELSWIDTH = 0x80000,
        DM_POSITION = 0x20
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct POINTL
    {
        [MarshalAs(UnmanagedType.I4)]
        public int x;
        [MarshalAs(UnmanagedType.I4)]
        public int y;
    }

    public class MultiDisplayHelper
    {
        private static readonly Lazy<MultiDisplayHelper> _instance = new Lazy<MultiDisplayHelper>(() => new MultiDisplayHelper());
        public static MultiDisplayHelper Instance => _instance.Value;

        private const int MONITOR_DEFAULTTONULL = 0;
        public const int DISP_CHANGE_SUCCESSFUL = 0;
        public const int DISP_CHANGE_RESTART = 1;
        public const int DISP_CHANGE_FAILED = -1;
        public const int CDS_TEST = 0x02;
        public const int CDS_UPDATEREGISTRY = 0x01;
        private Size _rollOutSize = new Size(2000, 2350);
        /// <summary> RollOut的分辨率 </summary>
        public Size RollOutSize { get { return _rollOutSize; } }

        private Size _rollInSize = new Size(2000, 1600);
        /// <summary> RollIn的分辨率 </summary>
        public Size RollInSize { get { return _rollInSize; } }
        public double CursonScreenDpi
        {
            get
            {
                return GetCursorScreenDpi();
            }
        }

        public IntPtr CursonScreenHwnd
        {
            get
            {
                return GetCursorScreenHwnd();
            }
        }

        public double MainScreenDpi
        {
            get
            {
                return GetMainScreenDpi();
            }
        }

        public IntPtr MainScreenHwnd
        {
            get
            {
                return GetMainScreenHwnd();
            }
        }

        public int MonitorCount
        {
            get
            {
                return GetSystemMetrics(SM_CMONITORS);
            }
        }


        private static readonly int SM_CMONITORS = 80;//桌面上的显示监视器数。

        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "GetSystemMetrics")]
        private static extern int GetSystemMetrics(int nIndex);

        [DllImport("user32.dll")]
        private static extern bool GetCursorPos(out POINTSTRUCT lpPoint);

        [DllImport("user32.dll")]
        private static extern IntPtr MonitorFromPoint(POINTSTRUCT pt, int dwFlags);

        [DllImport("user32.dll", EntryPoint = "GetMonitorInfoA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern bool GetMonitorInfo(IntPtr hmonitor, MONITORINFOEX info);

        [DllImport("SHcore.dll")]
        private static extern IntPtr GetDpiForMonitor([In] IntPtr hmonitor, [In] DpiType dpiType, [Out] out int dpiX, [Out] out int dpiY);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);

        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hwnd, ref Rect lpRect);


        #region 获取显示器设备信息

        public List<DeviceInfo> Devices
        {
            get; private set;
        }

        public string PrimaryDevID { get; private set; }

        public string SlateDisplayId = "LEN8BA7";

        public void GetDisplayDevices()
        {
            try
            {
                Devices = new List<DeviceInfo>();

                //Devices.Clear();

                int devIdx = 0;
                while (true)
                {

                    DISPLAY_DEVICE disDev = new();
                    disDev.cb = Marshal.SizeOf(disDev);
                    if (!EnumDisplayDevices(null, devIdx, ref disDev, 0))
                        break;

                    if (!disDev.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop))
                    {
                        devIdx++;
                        continue;
                    }

                    bool isPrimary = (disDev.StateFlags & DisplayDeviceStateFlags.PrimaryDevice) != 0;

                    string devName = disDev.DeviceName;
                    int subDevIdx = 0;
                    string deviceInstanceId = string.Empty;
                    while (true)
                    {
                        DISPLAY_DEVICE monitorInfo = new();
                        monitorInfo.cb = Marshal.SizeOf(monitorInfo);
                        bool findDisplay = EnumDisplayDevices(devName, subDevIdx++, ref monitorInfo, EDD_GET_DEVICE_INTERFACE_NAME);
                        if (findDisplay)
                        {
                            Logger.Instance.Info("MultiDisplayHelper", "GetDisplayDevices", $"subDevIdx:{subDevIdx} monitorInfo.StateFlags:{monitorInfo.StateFlags}");
                            if (!monitorInfo.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop))
                            {
                                //continue;
                            }
                            else
                            {
                                string deviceID = monitorInfo.DeviceID;
                                monitorInfo.DeviceName = devName;

                                if (monitorInfo.StateFlags != 0)
                                {
                                    Logger.Instance.Info("MultiDisplayHelper", "GetDisplayDevices", "isPrimary:" + isPrimary + " ,DeviceID：" + monitorInfo.DeviceID);


                                    if (!string.IsNullOrEmpty(monitorInfo.DeviceID))
                                    {
                                        string[] diviceIDList = monitorInfo.DeviceID.Split('#');
                                        if (diviceIDList.Length > 1)
                                        {
                                            if (isPrimary)
                                            {
                                                PrimaryDevID = monitorInfo.DeviceID.Split('#')[1];
                                            }
                                            else
                                            {
                                                deviceInstanceId = deviceID.Split('#')[1];
                                            }
                                        }
                                    }
                                }
                            }

                        }

                        DeviceInfo deviceInfo = new DeviceInfo();
                        deviceInfo.IsPrimary = isPrimary;
                        deviceInfo.DeviceID = deviceInstanceId;
                        deviceInfo.DeviceName = devName;
                        DEVMODE ndm = NewDevMode();
                        EnumDisplaySettings(devName, (int)DEVMODE_SETTINGS.ENUM_REGISTRY_SETTINGS, ref ndm);
                        deviceInfo.dm = ndm;

                        if (!Devices.Any(x => x.DeviceName.Equals(devName)))
                        {
                            Devices.Add(deviceInfo);
                        }
                        break;
                    }
                    devIdx++;
                    if (devIdx > 20)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Error("MultiDisplayHelper", "GetDisplayDevices", "GetDisplayDevices Error：" + ex.Message);
            }
        }

        public void QueryDisplayConfig()
        {

        }

        /// <summary>
        /// 当前系统支持的分辨率列表
        /// </summary>
        /// <returns></returns>
        public List<Size> GetScrennSizeList(string deviceName)
        {
            List<Size> CurenSetList = new List<Size>();
            int i = -1;
            string str = string.Empty;
            List<string> ls = new List<string>();
            DEVMODE DevM = new DEVMODE();
            bool mybool;
            mybool = EnumDisplaySettings(deviceName, i, ref DevM);
            while (mybool)
            {
                i = i + 1;
                Size cuSize = new Size(DevM.dmPelsWidth, DevM.dmPelsHeight);
                if (CurenSetList.IndexOf(cuSize) == -1)
                    CurenSetList.Add(cuSize);
                mybool = EnumDisplaySettings(deviceName, i, ref DevM);
            }
            return CurenSetList;
        }

        /// <summary>
        /// 修改分辨率
        /// </summary>
        /// <param name="deviceID">设备ID</param>
        /// <param name="size"></param>
        public void SetResolution(string deviceID, Size size)
        {
            // 初始化 DEVMODE结构
            DEVMODE devmode = new DEVMODE();
            devmode.dmDeviceName = new String(new char[32]);
            devmode.dmFormName = new String(new char[32]);
            devmode.dmSize = (ushort)Marshal.SizeOf(devmode);

            if (EnumDisplaySettings(deviceID, (int)DEVMODE_SETTINGS.ENUM_CURRENT_SETTINGS, ref devmode))
            {
                devmode.dmPelsWidth = (uint)size.Width;
                devmode.dmPelsHeight = (uint)size.Height;

                // 改变屏幕分辨率
                int iRet = ChangeDisplaySettingsEx(deviceID, ref devmode, (IntPtr)null, CDS_TEST, IntPtr.Zero);

                if (iRet == DISP_CHANGE_FAILED)
                {
                    //MessageBox.Show("不能执行你的请求");
                }
                else
                {
                    iRet = ChangeDisplaySettingsEx(deviceID, ref devmode, (IntPtr)null, CDS_UPDATEREGISTRY, IntPtr.Zero);
                    switch (iRet)
                    {
                        // 成功改变
                        case DISP_CHANGE_SUCCESSFUL:
                            {
                                //MessageBox.Show("改变屏幕分辨率成功");
                                break;
                            }
                        case DISP_CHANGE_RESTART:
                            {
                                //MessageBox.Show("你需要重新启动电脑设置才能生效");
                                break;
                            }
                        default:
                            {
                                //MessageBox.Show("改变屏幕分辨率失败");
                                break;
                            }
                    }
                }
            }
        }


        [Flags]
        public enum QueryDeviceConfigFlags : uint
        {
            QdcAllPaths = 0x00000001,
            QdcOnlyActivePaths = 0x00000002,
            QdcDatabaseCurrent = 0x00000004,
            QDC_VIRTUAL_MODE_AWARE = 0x00000010
        }

        private static DEVMODE NewDevMode()
        {
            DEVMODE dm = new DEVMODE();
            dm.dmDeviceName = new String(new char[31]);
            dm.dmFormName = new String(new char[31]);
            dm.dmSize = (ushort)Marshal.SizeOf(dm);
            return dm;
        }

        public const int EDD_GET_DEVICE_INTERFACE_NAME = 0x00000001;

        [DllImport("user32.dll")]
        public static extern int GetDisplayConfigBufferSizes(int flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
        [DllImport("user32.dll", EntryPoint = "ChangeDisplaySettingsEx")]
        public static extern int ChangeDisplaySettingsEx([In] string deviceName, [In] ref DEVMODE lpDevMode, IntPtr hwnd, int dwFlags, IntPtr lParam);
        [DllImport("user32.dll")]
        public static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);

        [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)]
        [DllImport("user32.dll")]
        public static extern bool EnumDisplayDevices(string lpDevice, int iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);

        [StructLayout(LayoutKind.Sequential)]
        public struct DISPLAY_DEVICE
        {
            [MarshalAs(UnmanagedType.U4)]
            public int cb;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string DeviceName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceString;
            [MarshalAs(UnmanagedType.U4)]
            public DisplayDeviceStateFlags StateFlags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceID;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string DeviceKey;

            public DISPLAY_DEVICE(int flags)
            {
                cb = 0;
                StateFlags = DisplayDeviceStateFlags.AttachedToDesktop;
                DeviceName = new string((char)32, 32);
                DeviceString = new string((char)32, 128);
                DeviceID = new string((char)32, 128);
                DeviceKey = new string((char)32, 128);
                cb = Marshal.SizeOf(this);
            }
        }

        [Flags()]
        public enum DisplayDeviceStateFlags : int
        {
            AttachedToDesktop = 0x1,//desktop 
            MultiDriver = 0x2,//multi 
            PrimaryDevice = 0x4,//primary 
            MirroringDriver = 0x8,//mirror 
            VGACompatible = 0x10,//vga 
            Removable = 0x20,
            ModesPruned = 0x8000000,
            Remote = 0x4000000,
            Disconnect = 0x2000000
        }
        #endregion

        /// <summary>
        /// 获取鼠标所在屏幕中心点坐标，返回的坐标是不计算DPI的
        /// </summary>
        /// <returns></returns>
        public System.Windows.Point GetCursorScreenCenterPoint()
        {
            System.Windows.Point centerPoint = new System.Windows.Point();
            GetCursorPos(out var pOINTSTRUCT);
            IntPtr monitorHwnd = MonitorFromPoint(pOINTSTRUCT, MONITOR_DEFAULTTONULL);
            MONITORINFOEX mONITORINFOEX = new MONITORINFOEX
            {
                cbSize = Marshal.SizeOf(typeof(MONITORINFOEX)),
            };

            bool result = GetMonitorInfo(monitorHwnd, mONITORINFOEX);
            if (result)
            {
                centerPoint.X = mONITORINFOEX.rcMonitor.left + (mONITORINFOEX.rcMonitor.right - mONITORINFOEX.rcMonitor.left) / 2;
                centerPoint.Y = mONITORINFOEX.rcMonitor.top + (mONITORINFOEX.rcMonitor.bottom - mONITORINFOEX.rcMonitor.top) / 2;
            }
            return centerPoint;
        }

        /// <summary>
        /// 获取鼠标所在屏幕左上角坐标和宽高，返回的数值是不计算DPI的
        /// </summary>
        /// <returns></returns>
        public System.Windows.Rect GetCursorScreenRect()
        {
            System.Windows.Rect rect = System.Windows.Rect.Empty;

            GetCursorPos(out var pOINTSTRUCT);
            IntPtr monitorHwnd = MonitorFromPoint(pOINTSTRUCT, MONITOR_DEFAULTTONULL);
            MONITORINFOEX mONITORINFOEX = new MONITORINFOEX
            {
                cbSize = Marshal.SizeOf(typeof(MONITORINFOEX)),
            };

            bool result = GetMonitorInfo(monitorHwnd, mONITORINFOEX);
            if (result)
            {
                rect.X = mONITORINFOEX.rcMonitor.left;
                rect.Y = mONITORINFOEX.rcMonitor.top;
                rect.Width = mONITORINFOEX.rcMonitor.right - mONITORINFOEX.rcMonitor.left;
                rect.Height = mONITORINFOEX.rcMonitor.bottom - mONITORINFOEX.rcMonitor.top;
            }
            return rect;
        }

        private double GetCursorScreenDpi()
        {
            double dpi = 0;

            GetCursorPos(out var pOINTSTRUCT);
            IntPtr monitorHwnd = MonitorFromPoint(pOINTSTRUCT, MONITOR_DEFAULTTONULL);
            GetDpiForMonitor(monitorHwnd, DpiType.Effective, out int dpiX, out int dpiY);

            dpi = Math.Round((double)dpiX / (double)96, 2);

            return dpi;
        }

        private IntPtr GetCursorScreenHwnd()
        {
            IntPtr monitorHwnd = IntPtr.Zero;

            GetCursorPos(out var pOINTSTRUCT);
            monitorHwnd = MonitorFromPoint(pOINTSTRUCT, MONITOR_DEFAULTTONULL);

            return monitorHwnd;
        }
        public static DeviceInfo GetShowMonitor()
        {
            MultiDisplayHelper.Instance.GetDisplayDevices();
            var allMonitors = MultiDisplayHelper.Instance.Devices;
            var primayDevice = allMonitors.First(f => f.IsPrimary);
            Logger.Instance.Info("MultiDisplayHelper", "GetShowMonitor", $"DeviceName:{primayDevice.DeviceName};ViewportBounds:{primayDevice.ViewportBounds}");

            return primayDevice;
        }


        private double GetMainScreenDpi()
        {
            double dpi = 0;
            IntPtr monitorHwnd = MonitorFromPoint(new POINTSTRUCT() { x = 1, y = 1 }, MONITOR_DEFAULTTONULL);
            GetDpiForMonitor(monitorHwnd, DpiType.Effective, out int dpiX, out int dpiY);
            dpi = Math.Round((double)dpiX / (double)96, 2);
            return dpi;
        }

        private IntPtr GetMainScreenHwnd()
        {
            IntPtr monitorHwnd = IntPtr.Zero;
            monitorHwnd = MonitorFromPoint(new POINTSTRUCT() { x = 1, y = 1 }, MONITOR_DEFAULTTONULL);
            return monitorHwnd;
        }

        public void ShowWindowToCursonScreenCenter(IntPtr hwnd)
        {
            Rect prc = new Rect();
            GetWindowRect(hwnd, ref prc);

            int w = (int)((prc.Right - prc.Left));
            int h = (int)((prc.Bottom - prc.Top));

            GetCursorPos(out var pOINTSTRUCT);

            IntPtr monitorHwnd = MonitorFromPoint(pOINTSTRUCT, MONITOR_DEFAULTTONULL);

            MONITORINFOEX mONITORINFOEX = new MONITORINFOEX
            {
                cbSize = Marshal.SizeOf(typeof(MONITORINFOEX)),
            };

            bool result = GetMonitorInfo(monitorHwnd, mONITORINFOEX);

            int Setleft = mONITORINFOEX.rcMonitor.left + (mONITORINFOEX.rcMonitor.right - mONITORINFOEX.rcMonitor.left - w) / 2;
            int SetTop = mONITORINFOEX.rcMonitor.top + (mONITORINFOEX.rcMonitor.bottom - mONITORINFOEX.rcMonitor.top - h) / 2;
            SetWindowPos(hwnd, 0, Setleft, SetTop, 0, 0,
                SetWindowPosFlags.IgnoreResize |
                SetWindowPosFlags.IgnoreZOrder |
                SetWindowPosFlags.DoNotActivate);
        }

        public void ShowChildWindowToMainWindowCenter(IntPtr childHwnd, IntPtr mainHwnd)
        {

        }

        /// <summary>
        /// 设置窗口显示在鼠标所在屏幕右侧显示
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="count">显示在第几个</param>
        public void ShowWindowToCursonScreenRight(IntPtr hwnd, int count)
        {
            Rect prc = new Rect();
            GetWindowRect(hwnd, ref prc);

            int w = (int)((prc.Right - prc.Left));
            int h = (int)((prc.Bottom - prc.Top));

            GetCursorPos(out var pOINTSTRUCT);

            IntPtr monitorHwnd = MonitorFromPoint(pOINTSTRUCT, MONITOR_DEFAULTTONULL);

            MONITORINFOEX mONITORINFOEX = new MONITORINFOEX
            {
                cbSize = Marshal.SizeOf(typeof(MONITORINFOEX)),
            };

            GetMonitorInfo(monitorHwnd, mONITORINFOEX);

            int Setleft = mONITORINFOEX.rcMonitor.left + (mONITORINFOEX.rcMonitor.right - mONITORINFOEX.rcMonitor.left - w * count);
            int SetTop = mONITORINFOEX.rcMonitor.top + (mONITORINFOEX.rcMonitor.bottom - mONITORINFOEX.rcMonitor.top - h * count);
            SetWindowPos(hwnd, 0, Setleft, SetTop, 0, 0,
                SetWindowPosFlags.IgnoreResize |
                SetWindowPosFlags.IgnoreZOrder |
                SetWindowPosFlags.DoNotActivate);
        }

        private struct Rect
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;

            public System.Windows.Rect ToRect() => new System.Windows.Rect((double)this.Left, (double)this.Top, (double)this.Right - (double)this.Left, (double)this.Bottom - (double)this.Top);
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
        public class MONITORINFOEX
        {
            public int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
            public RECT rcMonitor = new RECT();
            public RECT rcWork = new RECT();
            public int dwFlags = 0;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINTSTRUCT
        {
            public int x;
            public int y;
            public POINTSTRUCT(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }

        private enum DpiType
        {
            Effective = 0,
            Angular = 1,
            Raw = 2,
        }

        private enum SetWindowPosFlags : uint
        {
            SynchronousWindowPosition = 0x4000,
            DeferErase = 0x2000,
            DrawFrame = 0x0020,
            FrameChanged = 0x0020,
            HideWindow = 0x0080,
            DoNotActivate = 0x0010,
            DoNotCopyBits = 0x0100,
            IgnoreMove = 0x0002,
            DoNotChangeOwnerZOrder = 0x0200,
            DoNotRedraw = 0x0008,
            DoNotReposition = 0x0200,
            DoNotSendChangingEvent = 0x0400,
            IgnoreResize = 0x0001,
            IgnoreZOrder = 0x0004,
            ShowWindow = 0x0040,
        }
    }
}
